-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add WebRTC Signaling Protocol Spec #159
Conversation
Thanks for contributing! There is opportunity to generalise hole punching/STUN outside the domain of WebRTC. I’m thinking we should architect this solution around two components:
|
@raulk I would be receptive to making this spec more generalized as long as it still suits our needs for WebRTC. Can you elaborate on what you have in mind? |
Making an interface for signaling seems to fit the libp2p philosophy. I also think the current WebRTC implementations could be split further to fut the different interfaces: libp2p/go-libp2p-webrtc-direct#9, libp2p/go-libp2p-webrtc-direct#7.
|
Yes, that's exactly what I was thinking. In my prototype transport I was using Multiaddresses that look like:
This means you are dialing the peer identified by
Good idea. Is it more appropriate to let peers decide for themselves what they want the amount/size limits to be? Or do you think it should be part of the protocol? In any case the protocol should at least provide standardized error messages for rate-limiting. |
I wanted to define my meaning of 'signaling': exchange a bit of information between two peers so they can initiate a connection. Note that this doesn't include peer discovery, hole punching or NAT traversal. While also interesting, those aren't what we need to abstract to come to a generic WebRTC transport (a.k.a.: unify Next, It seems advisable to determine how far we want to abstract the signaling logic. Example possibilities:
The former would probably remain rather WebRTC specific. The latter is highly abstract and would be more generically applicable in libp2p. That being said, I'm not sure if we need to make it that generic. I don't know if/how many other protocols rely on an exchange of information between peers before a connection can be made, as is the case with WebRTC. Maybe the solution lies somewhere in the middle. |
@backkem I can't speak for everyone who might want to make use of a signaling server. For our use case (0x Mesh), the only bullet point in the "maximal" abstraction category that is useful is the last one: Signaling over the Transports already available to libp2p. There are two benefits to building the Signal Protocol to take advantage of existing libp2p Transports:
|
Just updated the spec proposal with some more information about multiaddress formats and how any existing libp2p transport can be used for signaling. |
Hey @albrow, I really like where this spec is going 👍 I think we should merge it in soon as a Working Draft and iterate on it in some more. I'm down to be on the interest group, so we just need two more people. @jacobheun @backkem @raulk - would any of you want to join as well? |
Yes, count me in. The foundations here look good and the overall direction would be of huge benefit to helping with moving browser solutions more decentralized. I agree with working to get this merged in as a working draft and iterating on it. Having an implementation of this that also supported an "auto-signal" option could provide a significant performance improvement to systems like the DHT. |
- Signaling over HTTP using a domain name: | ||
`/dns6/signaler.myapp.com/tcp/80/http/p2p-webrtc-signal/QmZbw3TKr3dxhHXiPkbNraWaeGoqPNXAXfAcV8RP2Eqngj` | ||
- Signaling via a common peer: | ||
`/p2p-webrtc-signal/QmWeRHDDiwuGnS4xbjF2zXETucL7xQLjadoaTZ4yJE3hQs` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I get this one? Is it missing the ID of the common peer acting as a signaller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It says above
<signaler-multiaddr>
may be omitted to use an existing connection to<signaler-peer-id>
for signaling.
But I'm also not entirely clear on the use case. Does this only work if I've already established a separate connection to the peer I want to reach (e.g. through a circuit relay)?
Or if we've both connected to any common peer that has the p2p-webrtc-signal capability, could I discover and use that without caring who the signaller peer is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or if we've both connected to any common peer that has the p2p-webrtc-signal capability, could I discover and use that without caring who the signaller peer is?
I think that not a good idea, a better solution could be to just indicate on the DHT we are reachable with WebRTC-signal and use a circuit relay to establish the connection.
So for that we need first a ws[s] connection to establish circuit relay and discover the DHT.
Adding some special nodes is a very good way to allow anybody to get a giant control on the network.
When these kind of option are made a very few people activate them, that made people less interested in making these because we know that gonna generate a big traffic.
In fact my solution add a problem about stun server but I think thats more a client side problem (by that I mean not a DHT one) 2, because 2 totaly separated STUN server produce some compatible result (except if you are not in the same network, example: internet and hyperboria), and some STUN server are region locked (China).
We may can just allow peers to run integrated STUN server and broadcast it to the DHT (to be apocalypsical proof) since that give you way less information (a meeting server know who talk to who, can chose who talk to who but can't create fake connection like Qmxxxx... is listening for WebRTC if we require signing these kind of information to a server capable of knowing this ip (so easly matchable with a peer id via DHT), want to connect to a WebRTC node).
PS: Meeting server can maybe be used only to broadcast "Qmxxxx is listening for WebRTC, contact him via circuit relay at this node" (signed by Qmxxxx for obvious reason) but in this case why not just putting these directly in DHT listen address of Qmxxxx ?
This is awesome, thank you. Yes, I'd be down to be in the Interest Group for this one, and I also would like @vyzo to sit on it. I'd like to explore integrating this protocol into the existing relay protocol, or finding angles for them to cooperate. Thoughts:
|
We should be able to have this work pretty easily leveraging circuit as the transport if the destination peer was also a signaler and we supported self signaling. Once we establish the connection over relay we can perform the signaling handshake. The destination peer could supply its own answer to the signaling offer and then establish the direct connection to the dialer, at which point we could end the relayed connection. Ideally the nodes would use autorelay to advertise their relay address, but in reality all we need is |
consider me counted as part of the interest group. |
Just wanted to point out that For some background, ICE involves gathering a list of "candidates" which are potential ways to connect to a peer. Candidates can be created by using a combination of STUN and TURN. So for example, as part of the "candidate gathering" process, you might perform hole punching with a specific STUN server. This takes time becaue it often involves sending requests to third-party servers and waiting for a response. Up until now I have written the spec with the assumption that all candidates will be gathered synchronously and the answers and offers that are passed between peers are complete (because up until now that was the way Trickle ICE is an optimization that makes the ICE candidate gathering process asynchronous instead of synchronous. It lets peers select the first candidate that works instead of waiting for all potential candidates to be gathered. In effect, this decreases the time it takes for two peers to connect. I'm going to update this spec with Trickle ICE in mind. This will probably mean adding a way for peers to update their answers/offers by adding new candidates as they are gathered. |
@albrow 👏 |
What about this proposal by @mkg20001 to do the signaling through a lightweight circuit protocol? libp2p/js-libp2p-webrtc-star#148 From what it seems, with it no intermediary peer needs to be specified. See also: |
Messages sent to the signaler are signed with a private key | ||
corresponding to that PeerID. This prevents tampering and impersontation. In | ||
other words, it ensures that a peer can only be connected to the peer that they | ||
intended to connect to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step is done for free when using libp2p Circuit Relay.
use the following multiaddress format for dialing and listening: | ||
|
||
``` | ||
<signaler-multiaddr>/p2p-webrtc-signal/<signaler-peer-id> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signaler-multiaddr can just be the relay address.
@albrow thank you so much for taking on this spec. Getting to a clear understanding of how WebRTC connections are established in the "normal world" and how they can be established in libp2p will get us to implement it correctly without using anything else other than libp2p nodes (so that any node can play the role, making the network more resilient). @Qmstream you hit the bullseye, in fact hat has been the goal since the very beginning 😁 I'll also add that there is actually no need to create yet another libp2p interface for data-exchange. It is literally just sending two (or a few) JSON objects with the respective SDP offers over any libp2p connection for the nodes that want to connect to each other. libp2p/js-libp2p#385 should provide more clarity of where we want to take the *-star protocols (i.e. to cease to exist). A few remarks/comments:
|
That approach makes a lot of sense and would solve some of the problems in the current version of the spec (mainly that it requires a custom multiaddr format and a unique multiaddr per peer that you're connected to, which is impractical). Can you point me to an existing spec for a transport upgrade that I could base this on? |
I'm very interested in working on a WebRTC project, using IPFS to distribute the video/audio. What is the status of any of the WebRTC/IPFS work that is in progress? I am particularly interested in using WebRTC One to Many broadcasting with IPFS distribution. Just not sure how to handle signaling? |
The current status is that there are a couple implementations:
This PR is an attempt at abstracting the signaling away from the transport so there would only be one WebRTC transport (per language) that can plug-in different signaling strategies. Another point of research is decentralizing the signaling. For example, by relaying it over already connected peers. If you're interested in video streaming over WebRTC you may be interested in adding WebRTC support to LivePeer media server: livepeer/lpms#38 |
You may also want to take go-webrtc-aside-transport into account. This uses WebRTC's native transport security and muxing and does signaling over existing connections. |
Summary
This PR introduces a draft specification for a WebRTC Signaling Protocol which can be used to establish a WebRTC connection between two peers.
At this time, the specification should be considered a work in progress. There are still some details to work out regarding signatures, message encoding, and error handling.
Additional Context
I know that there already has been some work done to add WebRTC support in the JavaScript implementation of libp2p (see js-libp2p-webrtc-direct and js-libp2p-webrtc-star) and there is also a community-contributed WebRTC transport for the Go implementation (see backkem/go-libp2p-webrtc-direct). However, AFAIK we do not yet have an agreed upon standard for establishing WebRTC connections.
The goal of this proposal is to have a single standard that can be used across all language implementations and is compatible with both non-browser peers (which have the ability to serve as the signaler themselves) and browser peers (which must rely on a third-party signaler).